#include "sg4c.h"
#include <time.h>
#include <math.h>

typedef struct{
    float x, y;
    float velx, vely;
} particle_t;

float cx=0, cy=0;

enum GLOBAL_CONST{
    PARTICLE_COUNT=2000,
    MAX_INIT_VELOCITY = 6,
    FPS = 30,
    TIME_DIVISION = 1,
};

particle_t particles[PARTICLE_COUNT];

inline float distance(float ax, float ay, float bx, float by){
    return sqrtf( powf(ax-bx, 2) + powf(ay-by, 2) );
}

void setup(){
    srand(time(NULL));
    int i=0;

    for( i=0; i<PARTICLE_COUNT; ++i ){
        particle_t * p = &particles[i];
        p->x = rand() % sgWidth();
        p->y = rand() % sgHeight();
        //~ p->velx =0;
        //~ p->vely = 0;
        p->velx =rand() % MAX_INIT_VELOCITY;
        p->vely =rand() % MAX_INIT_VELOCITY;
    }
}


void draw(){
    static int runOnce=1;
    if( runOnce ){
        sgNoStroke();
        sgFill( sgGray(0) );
        sgRect( 0, 0, sgWidth(), sgHeight() );

        cx = sgWidth()/2.0f;
        cy = sgHeight()/2.0f;
        runOnce=0;
    }

    sgNoStroke();
    sgFill( sgHexRGBA(0x10) );
    sgRect( 0, 0, sgWidth(), sgHeight() );

    int i=0;
    //draw
    sgStrokeWeight(1);
    sgStroke(sgGray(255));
    for( i=0; i<PARTICLE_COUNT; ++i ){
        const particle_t * const p = &particles[i];
        sgPoint( p->x, p->y );
    }
    sgNoStroke();
    sgFill( sgHexRGBA(0xff000080) );
    sgEllipse( cx-5, cy-5, 10, 10 );
    //update physics
    const float deltaT = 1.0f/FPS/TIME_DIVISION;

    for( i=0; i<PARTICLE_COUNT; ++i ){
        particle_t * p = &particles[i];

        //update position base on current velocity
        p->x += deltaT * p->velx;
        p->y += deltaT * p->vely;

        //update velocity base on current position

        const float REPULSION_RADIUS = 60;

        const float dist = distance( p->x, p->y, cx, cy);
        float force = 1*( 1-expf( -dist / REPULSION_RADIUS / 2.0f ) );
        const float cosine = (p->x - cx) / dist;
        const float sine = (p->y - cy) / dist;

        if( dist > REPULSION_RADIUS ){
            force = -force;
        }

        p->velx += cosine * force;
        p->vely += sine * force;
    }
}


//events
void mouseMoved(){
    //Mouse moved
    cx = sgMouse().x;
    cy = sgMouse().y;
}

void mousePressed(){
    //A mouse button is pressed
}

void mouseReleased(){
    //A mouse button is released
}

void mouseClicked(){
    //A mouse button is pressed and released
}

void mouseDragged(){
    //The mouse moves when being pressed
}

void mouseEntered(){
    //The mouse pointer enters the display frame
}

void mouseExited(){
    //The mouse pointer leaves the display frame
}

void keyReleased(){
    //A key is released
}

void keyPressed(){
    //A key is pressed
}

void keyTyped(){
    //A key is pressed and then released
}

int main(){
    sg_config_t config;
    sgInitConfig( &config );

    config.screen.width = 900;  //set the horizontal resolution of the frame
    config.screen.height = 600; //set the vertical resolution of the frame
    config.framerate = FPS;      //set the per-second framerate


    //config.smooth = 1; // uncomment this line to enable smoothing

    //------------------------------------------------------------------
    //DO NOT MODIFY CODE BELOW

    //setup callbacks
    config.setup = setup;
    config.draw = draw;

    config.mousePressed = mousePressed;
    config.mouseReleased = mouseReleased;
    config.mouseMoved = mouseMoved;
    config.mouseEntered = mouseEntered;
    config.mouseExited = mouseExited;
    config.mouseClicked = mouseClicked;
    config.mouseDragged = mouseDragged;

    config.keyReleased = keyReleased;
    config.keyPressed = keyPressed;
    config.keyTyped = keyTyped;

    //initilize the system
    sgSetup(&config);

    //run forever
    return sgRunForever();
}
